home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ASME's Mechanical Engine…ing Toolkit 1997 December
/
ASME's Mechanical Engineering Toolkit 1997 December.iso
/
c_lang
/
super_c.lzh
/
SQUIG.C
< prev
next >
Wrap
Text File
|
1980-01-01
|
11KB
|
274 lines
/* Fractal Generation Program
*/
#include <stdio.h>
#include <math.h>
#define FALSE 0
#define TRUE 1
/* Movement directions: */
#define UP 0
#define DOWN 1
#define LEFT 2
#define RIGHT 3
/* Table to convert from the direction of a segment being drawn (first
index) and the direction of a subsegment (second index) to absolute
screen up/down/left/right: */
int dirDir[4][4] = {
LEFT, RIGHT, DOWN, UP, /* Line up. */
RIGHT, LEFT, UP, DOWN, /* Line down. */
DOWN, UP, RIGHT, LEFT, /* Line left. */
UP, DOWN, LEFT, RIGHT /* Line right. */
};
/* X-axis multiplier for up/down/left/right movement: */
int xDir[4] = {
0, 0, -1, 1 /* Line right. */
};
/* Y-axis multiplier for up/down/left/right movement: */
int yDir[4] = {
-1, 1, 0, 0 /* Line right. */
};
int boxPatt[100]; /* The box pattern. */
int boxPSz; /* It's size. */
int linePatt[100]; /* The line pattern. */
int linePSz; /* It's size. */
int lineLen; /* Width of line pattern in line segments. */
int level; /* The level of detail to go to. */
float x, y; /* The current pen position. */
int color; /* The current pen color. */
/* main()
Function: Get box and line patterns, the line size, and the
level to draw to from the user. Then draw the fractal. When
done, ask if another one should be drawn. Repeat the sequence
as long as the user wants.
Algorithm: Use getPatt to read in the patterns for the box and
the line pattern. Use gets/atoi for the other, numeric input.
Then call doPatt to actually draw the fractal.
*/
main()
{
char str[100]; /* Input buffer for user responses. */
int side; /* Size of line in screen dots. */
/* Repeat while the user wants more. */
do {
/* Set the display mode; use 6 for CGA, 14 for EGA with
color display, or 16 for EGA with enhanced color disp. */
setMod(6);
/* Get the box pattern. */
getPatt("box",boxPatt,&boxPSz,TRUE,TRUE);
/* Get the size of the box line. */
printf("Side size: ");
gets(str);
side = atoi(str);
/* Get the line pattern. */
lineLen = getPatt("line",linePatt,&linePSz,TRUE,FALSE);
/* Get the level to display to. */
printf("Level: ");
gets(str);
level = atoi(str);
/* Set the pen position and color to start with. */
x = 270; y = 50; color = 7;
/* Draw the fractal. */
doPatt(boxPatt,boxPSz,RIGHT,(float) side,0);
/* Ask if the user wants to do another one. */
printf("Do another one? ");
gets(str);
} while ((str[0] == 'y') || (str[0] == 'Y'));
}
/* getPatt(prmpt,patt,size,noUp,noLeft)
Function: Get a pattern from the user. Issue the prompt
string pointed to by prmpt. Then read the pattern into
the pattern array pointed to by patt, and set the size
pointed to by size. If noUp is TRUE, don't allow patterns
that end at a different up/down level than they began.
If noLeft is TRUE, don't allow patterns that end at a
different left/right level than they started. getPatt
returns the number of segments to the right the pattern
ends at from its starting position.
Algorithm: Prompt the user and then read in the pattern
string. Scan through it, converting from 'u'/'d'/'l'/'r'
to UP/DOWN/LEFT/RIGHT. When done, check it for validity.
If it fails, tell the user and do it all over again.
*/
getPatt(prmpt,patt,size,noUp,noLeft)
char *prmpt;
int *patt;
int *size;
int noUp;
int noLeft;
{
char str[100]; /* Input buffer for user input. */
char *cp; /* Char pointer to scan buffer with. */
int *pPtr; /* Pattern array pointer. */
int upCnt, rightCnt; /* Up/down and left/right offsets. */
int badPatt; /* TRUE if pattern is bad. */
/* Repeat until he gets it right. */
do {
/* Prompt him for a pattern string. */
printf("Enter %s pattern: ",prmpt); gets(str);
/* Assume the pattern's OK. */
badPatt = FALSE;
/* Scan through the pattern string. */
for (cp = str, pPtr = patt, upCnt = rightCnt = 0, *size = 0;
*cp != 0; cp++, pPtr++, (*size)++) {
switch (*cp) {
case 'u':
case 'U':
/* Up one. */
*pPtr = UP;
upCnt++;
break;
case 'd':
case 'D':
/* Down one. */
*pPtr = DOWN;
upCnt--;
break;
case 'l':
case 'L':
/* Left one. */
*pPtr = LEFT;
rightCnt--;
break;
case 'r':
case 'R':
*pPtr = RIGHT;
rightCnt++;
break;
default:
badPatt = TRUE;
break;
};
if (badPatt) {
printf("Only U, D, L, or R allowed!\n");
break;
};
};
if (noUp && (upCnt != 0)) {
printf("Pattern must end at the same up/down level ");
printf("it began at.\n");
badPatt = TRUE;
};
if (noLeft && (rightCnt != 0)) {
printf("Pattern must end at the same right/left ");
printf("level it began at.\n");
badPatt = TRUE;
};
} while (badPatt);
return(rightCnt);
}
/* doPatt(patt,pattSize,dir,size,lev)
Function: Draw the pattern pointed to by patt, of size pattSize,
in the direction dir (UP, DOWN, LEFT, or RIGHT), with each line
segment of size size; this will be level lev. If lev doesn't yet
match the global variable level, then recursively call doPatt to
draw each segment as a series of segments from the line pattern.
Algorithm: For each segment in the pattern, if we're at the drawing
level (lev == level), then figure out the proper direction to
draw and draw the segment; otherwise, call doPatt to draw the
sub-pattern.
*/
doPatt(patt,pattSize,dir,size,lev)
int *patt;
int pattSize;
int dir;
float size;
int lev;
{
int *pPtr; /* A pointer into the pattern. */
int pCnt; /* Count of pattern segments left. */
int xPlusMinus, yPlusMinus; /* The x and y drawing increments. */
register int i, j; /* Row and column drawing indices. */
int iEnd, jEnd; /* Where to stop drawing. */
int temp;
int subDir; /* The absolute up/down/left/right. */
int dotVal; /* Color to draw. */
/* For each segment in the pattern... */
for (pPtr = patt, pCnt = 0; pCnt++ < pattSize; pPtr++) {
/* If we're at drawing level... */
if (lev == level) {
/* Find the absolute direction. */
subDir = dirDir[dir][*pPtr];
/* Convert the pen position to row/column ints. */
i = x; j = y;
/* Get the pen increment for drawing. */
xPlusMinus = xDir[subDir];
yPlusMinus = yDir[subDir];
/* Compute the new pen position after drawing. */
x += xPlusMinus*size; y += yPlusMinus*size;
/* Convert the end point to row/column ints. */
iEnd = x; jEnd = y;
/* We always want to draw in ascending coordinates.
Therefore, we must swap i/iEnd and j/jEnd if
we'd be drawing descending. */
if (iEnd < i) {
temp = i; i = iEnd; iEnd = temp;
};
if (jEnd < j) {
temp = j; j = jEnd; jEnd = temp;
};
/* Similarly, we need the abs of the increments. */
xPlusMinus = abs(xPlusMinus);
yPlusMinus = abs(yPlusMinus);
/* Set the color to draw. For the EGA, this should
be the global variable color; for CGA, it should
be 1. */
dotVal = 1 /*color*/;
/* Decide whether we're drawing a vertical or
horizontal line. */
if (xPlusMinus == 0) {
/* If vertical, draw it. */
do putDot(0,j++,i,dotVal); while (j < jEnd);
} else {
/* If horizontal, draw it. */
do putDot(0,j,i++,dotVal); while (i < iEnd);
};
/* If we're not down to drawing level yet, call doPatt to
draw the next level down. */
} else doPatt(linePatt,linePSz,dirDir[dir][*pPtr],
size/((float) lineLen),lev+1);
/* If this is the top level, switch to the next color for
drawing the next segment. */
if (lev == 0) {
color--;
if (color == 0) color = 15;
};
};
}